home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / muds / mordor_2.000 / mordor_2 / util / ed / files2.c < prev    next >
C/C++ Source or Header  |  1992-10-21  |  17KB  |  721 lines

  1. /*
  2.  * FILES2.C:
  3.  *
  4.  *    Additional file routines, including memory management.
  5.  *
  6.  *    Copyright (C) 1991 Brett J. Vickers
  7.  *
  8.  */
  9.  
  10. #include "mstruct.h"
  11. #include "mextern.h"
  12.  
  13. typedef struct queue_tag {        /* General queue tag data struct */
  14.     int            index;
  15.     struct queue_tag    *next;
  16.     struct queue_tag    *prev;
  17. } qtag;
  18.  
  19. typedef struct rsparse {        /* Sparse pointer array for rooms */
  20.     room             *rom;
  21.     qtag            *q_rom;
  22. } rsparse;
  23.  
  24. typedef struct csparse {        /* Sparse pointer array for creatures */
  25.     creature        *crt;
  26.     qtag            *q_crt;
  27. } csparse;
  28.  
  29. typedef struct osparse {        /* Sparse pointer array for objects */
  30.     object            *obj;
  31.     qtag            *q_obj;
  32. } osparse;
  33.  
  34. static rsparse    Rom[RMAX];    /* Pointer array declared */
  35. static csparse    Crt[CMAX];
  36. static osparse    Obj[OMAX];
  37.  
  38. static qtag    *Romhead=0;    /* Queue header and tail pointers */
  39. static qtag    *Romtail=0;
  40. static qtag    *Crthead=0;
  41. static qtag    *Crttail=0;
  42. static qtag    *Objhead=0;
  43. static qtag    *Objtail=0;
  44.  
  45. static int    Rsize=0;    /* Queue sizes */
  46. static int    Csize=0;
  47. static int    Osize=0;
  48.  
  49. /**********************************************************************/
  50. /*                load_rom                  */
  51. /**********************************************************************/
  52.  
  53. /* This function accepts a room number as its first argument and then   */
  54. /* returns a dblpointer to that room's data in the second parameter.    */
  55. /* If the room has already been loaded, the pointer is simply returned. */
  56. /* Otherwise, the room is loaded into memory.  If a maximal number of   */
  57. /* rooms is already in the memory, then the least recently used room    */
  58. /* is stored back to disk, and the memory is freed.                */
  59.  
  60. int load_rom(index, rom_ptr)
  61. short    index;
  62. room    **rom_ptr;
  63. {
  64.     int    fd;
  65.     qtag    *qt;
  66.     char    file[256];
  67.  
  68.     if(index >= RMAX || index < 0)
  69.         return(-1);
  70.  
  71.     /* Check if room is already loaded, and if so return pointer */
  72.  
  73.     if(Rom[index].rom) {
  74.         front_queue(&Rom[index].q_rom, &Romhead, &Romtail, &Rsize);
  75.         *rom_ptr = Rom[index].rom;
  76.     }
  77.  
  78.     /* Otherwise load the room, store rooms if queue size becomes */
  79.     /* too big, and return a pointer to the newly loaded room     */
  80.  
  81.     else {
  82.         sprintf(file, "%s/r%05d", ROOMPATH, index);
  83.         fd = open(file, O_RDONLY, 0);
  84.         if(fd < 0)
  85.             return(-1);
  86.         *rom_ptr = (room *)malloc(sizeof(room));
  87.         if(!*rom_ptr)
  88.             merror("load_rom", FATAL);
  89.         if(read_rom(fd, *rom_ptr) < 0) {
  90.             close(fd);
  91.             return(-1);
  92.         }
  93.         close(fd);
  94.  
  95.         (*rom_ptr)->rom_num = index;
  96.  
  97.         qt = (qtag *)malloc(sizeof(qtag));
  98.         if(!qt)
  99.             merror("load_rom", FATAL);
  100.         qt->index = index;
  101.         Rom[index].rom = *rom_ptr;
  102.         Rom[index].q_rom = qt;
  103.         put_queue(&qt, &Romhead, &Romtail, &Rsize);
  104.  
  105.         while(Rsize > RQMAX) {
  106.  
  107.             pull_queue(&qt, &Romhead, &Romtail, &Rsize);
  108.             if(Rom[qt->index].rom->first_ply) {
  109.                 put_queue(&qt, &Romhead, &Romtail, &Rsize);
  110.                 continue;
  111.             }
  112.             sprintf(file, "%s/r%05d", ROOMPATH, qt->index);
  113.             unlink(file);
  114.             fd = open(file, O_RDWR | O_CREAT, ACC);
  115.             if(fd < 1)
  116.                 return(-1);
  117.             if(!Rom[qt->index].rom)
  118.                 merror("load_rom", NONFATAL);
  119.             if(write_rom(fd, Rom[qt->index].rom, PERMONLY) < 0) {
  120.                 close(fd);
  121.                 return(-1);
  122.             }
  123.             close(fd);
  124.             free_rom(Rom[qt->index].rom);
  125.             Rom[qt->index].rom = 0;
  126.             free(qt);
  127.         }
  128.     }
  129.  
  130.     return(0);
  131.  
  132. }
  133.  
  134. int is_rom_loaded(num)
  135. int    num;
  136. {
  137.     return(Rom[num].rom != 0);
  138. }
  139.  
  140. /**********************************************************************/
  141. /*                reload_rom                  */
  142. /**********************************************************************/
  143.  
  144. /* This function reloads a room from disk, if it's already loaded.  This  */
  145. /* allows you to make changes to a room, and then reload it, even if it's */
  146. /* already in the memory room queue.                      */
  147.  
  148. int reload_rom(num)
  149. int    num;
  150. {
  151.     room    *rom_ptr;
  152.     ctag    *cp;
  153.     otag    *op;
  154.     char    file[80];
  155.     int    fd;
  156.  
  157.     if(!Rom[num].rom)
  158.         return(0);
  159.  
  160.     sprintf(file, "%s/r%05d", ROOMPATH, num);
  161.     fd = open(file, O_RDONLY, 0);
  162.     if(fd < 0)
  163.         return(-1);
  164.     rom_ptr = (room *)malloc(sizeof(room));
  165.     if(!rom_ptr)
  166.         merror("reload_rom", FATAL);
  167.     if(read_rom(fd, rom_ptr) < 0) {
  168.         close(fd);
  169.         return(-1);
  170.     }
  171.     close(fd);
  172.  
  173.     rom_ptr->first_ply = Rom[num].rom->first_ply;
  174.     Rom[num].rom->first_ply = 0;
  175.  
  176.     if(!rom_ptr->first_mon) {
  177.         rom_ptr->first_mon = Rom[num].rom->first_mon;
  178.         Rom[num].rom->first_mon = 0;
  179.     }
  180.  
  181.     if(!rom_ptr->first_obj) {
  182.         rom_ptr->first_obj = Rom[num].rom->first_obj;
  183.         Rom[num].rom->first_obj = 0;
  184.     }
  185.  
  186.     free_rom(Rom[num].rom);
  187.     Rom[num].rom = rom_ptr;
  188.  
  189.     cp = rom_ptr->first_ply;
  190.     while(cp) {
  191.         cp->crt->parent_rom = rom_ptr;
  192.         cp = cp->next_tag;
  193.     }
  194.  
  195.     cp = rom_ptr->first_mon;
  196.     while(cp) {
  197.         cp->crt->parent_rom = rom_ptr;
  198.         cp = cp->next_tag;
  199.     }
  200.  
  201.     op = rom_ptr->first_obj;
  202.     while(op) {
  203.         op->obj->parent_rom = rom_ptr;
  204.         op = op->next_tag;
  205.     }
  206.  
  207.     return(0);
  208.  
  209. }
  210.  
  211. /**********************************************************************/
  212. /*                resave_rom                  */
  213. /**********************************************************************/
  214.  
  215. /* This function saves an already-loaded room back to memory without */
  216. /* altering its position on the queue.                     */
  217.  
  218. int resave_rom(num)
  219. int    num;
  220. {
  221.     char    file[80];
  222.     int    fd;
  223.  
  224.     if(!Rom[num].rom)
  225.         return(0);
  226.  
  227.     sprintf(file, "%s/r%05d", ROOMPATH, num);
  228.     unlink(file);
  229.     fd = open(file, O_RDWR | O_CREAT, ACC);
  230.     if(fd < 1)
  231.         return(-1);
  232.     if(!Rom[num].rom)
  233.         merror("resave_rom", NONFATAL);
  234.     if(write_rom(fd, Rom[num].rom, PERMONLY) < 0) {
  235.         close(fd);
  236.         return(-1);
  237.     }
  238.     close(fd);
  239.  
  240.     return(0);
  241.  
  242. }
  243.  
  244. /**********************************************************************/
  245. /*                resave_all_rom                  */
  246. /**********************************************************************/
  247.  
  248. /* This function saves all memory-resident rooms back to disk.  If the */
  249. /* permonly parameter is non-zero, then only permanent items in those  */
  250. /* rooms are saved back.                           */
  251.  
  252. void resave_all_rom(permonly)
  253. int    permonly;
  254. {
  255.     qtag     *qt;
  256.     char    file[80];
  257.     int    fd;
  258.  
  259.     qt = Romhead;
  260.     while(qt) {
  261.         if(!Rom[qt->index].rom) {
  262.             qt = qt->next;
  263.             continue;
  264.         }
  265.  
  266.         sprintf(file, "%s/r%05d", ROOMPATH, qt->index);
  267.         fd = open(file, O_RDWR | O_CREAT, ACC);
  268.         if(fd < 1)
  269.             return;
  270.         if(write_rom(fd, Rom[qt->index].rom, permonly) < 0) {
  271.             close(fd);
  272.             return;
  273.         }
  274.         close(fd);
  275.         qt = qt->next;
  276.     }
  277. }
  278.  
  279. /**********************************************************************/
  280. /*                save_all_ply                  */
  281. /**********************************************************************/
  282.  
  283. /* This function saves all players currently in memory.              */
  284.  
  285. void save_all_ply()
  286. {
  287.     int i;
  288.  
  289.     for(i=2; i<Tablesize; i++) {
  290.         if(Ply[i].ply && Ply[i].io && Ply[i].ply->name[0])
  291.             savegame(Ply[i].ply, 0);
  292.     }
  293. }
  294.  
  295. /**********************************************************************/
  296. /*                flush_rom                  */
  297. /**********************************************************************/
  298.  
  299. /* This function flushes out the room queue and clears the room sparse */
  300. /* pointer array, without saving anything to file.  It also clears all */
  301. /* memory used by loaded rooms.  Call this function before leaving the */
  302. /* program.                                   */
  303.  
  304. void flush_rom()
  305. {
  306.     qtag *qt;
  307.  
  308.     while(1) {
  309.         pull_queue(&qt, &Romhead, &Romtail, &Rsize);
  310.         if(!qt) break;
  311.         free_rom(Rom[qt->index].rom);
  312.         Rom[qt->index].rom = 0;
  313.         free(qt);
  314.     }
  315. }
  316.  
  317. /**********************************************************************/
  318. /*                flush_crt                  */
  319. /**********************************************************************/
  320.  
  321. /* This function flushes out the monster queue and clears the monster */
  322. /* sparse pointer array without saving anything to file.  It also     */
  323. /* clears all memory used by loaded creatures.  Call this function    */
  324. /* before leaving the program.                          */
  325.  
  326. void flush_crt()
  327. {
  328.     qtag *qt;
  329.  
  330.     while(1) {
  331.         pull_queue(&qt, &Crthead, &Crttail, &Csize);
  332.         if(!qt) break;
  333.         free_crt(Crt[qt->index].crt);
  334.         Crt[qt->index].crt = 0;
  335.         free(qt);
  336.     }
  337. }
  338.  
  339. /**********************************************************************/
  340. /*                flush_obj                  */
  341. /**********************************************************************/
  342.  
  343. /* This function flushes out the object queue and clears the object */
  344. /* sparse pointer array without saving anything to file.  It also   */
  345. /* clears all memory used by loaded objects.  Call this function    */
  346. /* leaving the program.                            */
  347.  
  348. void flush_obj()
  349. {
  350.     qtag *qt;
  351.  
  352.     while(1) {
  353.         pull_queue(&qt, &Objhead, &Objtail, &Osize);
  354.         if(!qt) break;
  355.         free_obj(Obj[qt->index].obj);
  356.         Obj[qt->index].obj = 0;
  357.         free(qt);
  358.     }
  359. }
  360.  
  361. /**********************************************************************/
  362. /*                load_crt                  */
  363. /**********************************************************************/
  364.  
  365. /* This function returns a pointer to the monster given by the index in */
  366. /* the first parameter.  The pointer is returned in the second.  If the */
  367. /* monster is already in memory, then a pointer is merely returned.     */
  368. /* Otherwise, the monster is loaded into memory and a pointer is re-    */
  369. /* turned.  If there are too many monsters in memory, then the least    */
  370. /* recently used one is freed from memory.                */
  371.  
  372. int load_crt(index, mon_ptr)
  373. short        index;
  374. creature    **mon_ptr;
  375. {
  376.     int    fd;
  377.     long    n;
  378.     qtag    *qt;
  379.     char    file[256];
  380.  
  381.     if(index >= CMAX || index < 0)
  382.         return(-1);
  383.  
  384.     /* Check if monster is already loaded, and if so return pointer */
  385.  
  386.     if(Crt[index].crt) {
  387.         front_queue(&Crt[index].q_crt, &Crthead, &Crttail, &Csize);
  388.         *mon_ptr = (creature *)malloc(sizeof(creature));
  389.         **mon_ptr = *Crt[index].crt;
  390.     }
  391.  
  392.     /* Otherwise load the monster, erase monsters if queue size          */
  393.     /* becomes too big, and return a pointer to the newly loaded monster */
  394.  
  395.     else {
  396.         sprintf(file, "%s/m%02d", MONPATH, index/MFILESIZE);
  397.         fd = open(file, O_RDONLY, 0);
  398.         if(fd < 0) {
  399.             *mon_ptr = 0;
  400.             return(-1);
  401.         }
  402.         *mon_ptr = (creature *)malloc(sizeof(creature));
  403.         if(!*mon_ptr)
  404.             merror("load_crt", FATAL);
  405.         n = lseek(fd, (long)((index%MFILESIZE)*sizeof(creature)), 0);
  406.         if(n < 0L) {
  407.             free(*mon_ptr);
  408.             close(fd);
  409.             *mon_ptr = 0;
  410.             return(-1);
  411.         }
  412.         n = read(fd, *mon_ptr, sizeof(creature));
  413.         close(fd);
  414.         if(n < sizeof(creature)) {
  415.             free(*mon_ptr);
  416.             *mon_ptr = 0;
  417.             return(-1);
  418.         }
  419.  
  420.         (*mon_ptr)->fd = -1;
  421.         qt = (qtag *)malloc(sizeof(qtag));
  422.         if(!qt)
  423.             merror("load_crt", FATAL);
  424.         qt->index = index;
  425.         Crt[index].crt = (creature *)malloc(sizeof(creature));
  426.         *Crt[index].crt = **mon_ptr;
  427.         Crt[index].q_crt = qt;
  428.         put_queue(&qt, &Crthead, &Crttail, &Csize);
  429.  
  430.         while(Csize > CQMAX) {
  431.             pull_queue(&qt, &Crthead, &Crttail, &Csize);
  432.             free_crt(Crt[qt->index].crt);
  433.             Crt[qt->index].crt = 0;
  434.             free(qt);
  435.         }
  436.     }
  437.  
  438.     (*mon_ptr)->lasttime[LT_HEALS].ltime = time(0);
  439.     (*mon_ptr)->lasttime[LT_HEALS].interval = 60L;
  440.  
  441.     return(0);
  442.  
  443. }
  444.  
  445. /**********************************************************************/
  446. /*                load_obj                  */
  447. /**********************************************************************/
  448.  
  449. /* This function loads the object specified by the first parameter, and */
  450. /* returns a pointer to it in the second parameter.  If the object has  */
  451. /* already been loaded before, then a pointer is merely returned.       */
  452. /* Otherwise, the object is loaded into memory and the pointer is       */
  453. /* returned.  If there are too many objects in memory, then the least   */
  454. /* recently used objects are freed from memory.                */
  455.  
  456. int load_obj(index, obj_ptr)
  457. short    index;
  458. object    **obj_ptr;
  459. {
  460.     int    fd;
  461.     long    n;
  462.     qtag    *qt;
  463.     char    file[256];
  464.  
  465.     if(index >= OMAX || index < 0)
  466.         return(-1);
  467.  
  468.     /* Check if object is already loaded, and if so return pointer */
  469.  
  470.     if(Obj[index].obj) {
  471.         front_queue(&Obj[index].q_obj, &Objhead, &Objtail, &Osize);
  472.         *obj_ptr = (object *)malloc(sizeof(object));
  473.         **obj_ptr = *Obj[index].obj;
  474.     }
  475.  
  476.     /* Otherwise load the object, erase objects if queue size           */
  477.     /* becomes too big, and return a pointer to the newly loaded object */
  478.  
  479.     else {
  480.         sprintf(file, "%s/o%02d", OBJPATH, index/OFILESIZE);
  481.         fd = open(file, O_RDONLY, 0);
  482.         if(fd < 0)
  483.             return(-1);
  484.         *obj_ptr = (object *)malloc(sizeof(object));
  485.         if(!*obj_ptr)
  486.             merror("load_obj", FATAL);
  487.         n = lseek(fd, (long)((index%OFILESIZE)*sizeof(object)), 0);
  488.         if(n < 0L) {
  489.             close(fd);
  490.             return(-1);
  491.         }
  492.         n = read(fd, *obj_ptr, sizeof(object));
  493.         close(fd);
  494.         if(n < sizeof(object))
  495.             return(-1);
  496.  
  497.         qt = (qtag *)malloc(sizeof(qtag));
  498.         if(!qt)
  499.             merror("load_obj", FATAL);
  500.         qt->index = index;
  501.         Obj[index].obj = (object *)malloc(sizeof(object));
  502.         *Obj[index].obj = **obj_ptr;
  503.         Obj[index].q_obj = qt;
  504.         put_queue(&qt, &Objhead, &Objtail, &Osize);
  505.         while(Osize > OQMAX) {
  506.             pull_queue(&qt, &Objhead, &Objtail, &Osize);
  507.             free_obj(Obj[qt->index].obj);
  508.             Obj[qt->index].obj = 0;
  509.             free(qt);
  510.         }
  511.     }
  512.  
  513.     return(0);
  514.  
  515. }
  516.  
  517. /***********************************************************************/
  518. /*                save_ply                   */
  519. /***********************************************************************/
  520.  
  521. /* This function saves the player specified by the string in the first */
  522. /* parameter, and uses the player in the second parameter.           */
  523.  
  524. int save_ply(str, ply_ptr)
  525. char        *str;
  526. creature    *ply_ptr;
  527. {
  528.     char    file[80];
  529.     int    fd, n;
  530. #ifdef COMPRESS
  531.     char    *a_buf, *b_buf;
  532.     int    size;
  533. #endif
  534.  
  535.     sprintf(file, "%s/%s", PLAYERPATH, str);
  536.     unlink(file);
  537.     fd = open(file, O_RDWR | O_CREAT, ACC);
  538.     if(fd < 0)
  539.         return(-1);
  540.  
  541. #ifdef COMPRESS
  542.     a_buf = (char *)malloc(80000);
  543.     if(!a_buf) merror(FATAL, "Memory allocation");
  544.     n = write_crt_to_mem(a_buf, ply_ptr, 0);
  545.     if(n > 80000) merror(FATAL, "Player too large");
  546.     b_buf = (char *)malloc(n);
  547.     if(!b_buf) merror(FATAL, "Memory allocation");
  548.     size = compress(a_buf, b_buf, n);
  549.     n = write(fd, b_buf, size);
  550.     free(a_buf);
  551.     free(b_buf);
  552. #else
  553.     n = write_crt(fd, ply_ptr, 0);
  554.     if(n < 0) {
  555.         close(fd);
  556.         return(-1);
  557.     }
  558. #endif
  559.  
  560.     close(fd);
  561.     return(0);
  562.  
  563. }
  564.  
  565. /***********************************************************************/
  566. /*                load_ply                   */
  567. /***********************************************************************/
  568.  
  569. /* This function loads the player specified by the string in the first */
  570. /* parameter, and returns the player in the second parameter.           */
  571.  
  572. int load_ply(str, ply_ptr)
  573. char        *str;
  574. creature    **ply_ptr;
  575. {
  576.     char    file[80];
  577.     int    fd, n;
  578. #ifdef COMPRESS
  579.     char    *a_buf, *b_buf;
  580.     int    size;
  581. #endif
  582.  
  583.     sprintf(file, "%s/%s", PLAYERPATH, str);
  584.     fd = open(file, O_RDONLY, 0);
  585.     if(fd < 0) 
  586.         return(-1);
  587.  
  588.     *ply_ptr = (creature *)malloc(sizeof(creature));
  589.     if(!*ply_ptr)
  590.         merror("load_ply", FATAL);
  591.  
  592. #ifdef COMPRESS
  593.     a_buf = (char *)malloc(30000);
  594.     if(!a_buf) merror(FATAL, "Memory allocation");
  595.     size = read(fd, a_buf, 30000);
  596.     if(size >= 30000) merror(FATAL, "Player too large");
  597.     if(size < 1) {
  598.         close(fd);
  599.         return(-1);
  600.     }
  601.     b_buf = (char *)malloc(80000);
  602.     if(!b_buf) merror(FATAL, "Memory allocation");
  603.     n = uncompress(a_buf, b_buf, size);
  604.     if(n > 80000) merror(FATAL, "Player too large");
  605.     n = read_crt_from_mem(b_buf, *ply_ptr, 0);
  606.     free(a_buf);
  607.     free(b_buf);
  608. #else
  609.     n = read_crt(fd, *ply_ptr);
  610.     if(n < 0) {
  611.         close(fd);
  612.         return(-1);
  613.     }
  614. #endif
  615.  
  616.     close(fd);
  617.     return(0);
  618.  
  619. }
  620.  
  621. /**********************************************************************/
  622. /*                put_queue                  */
  623. /**********************************************************************/
  624.  
  625. /* put_queue places the queue tag pointed to by the first paramater onto */
  626. /* a queue whose head and tail tag pointers are the second and third     */
  627. /* parameters.  If parameters 2 & 3 are 0, then a new queue is created.  */
  628. /* The fourth parameter points to a queue size counter which is      */
  629. /* incremented.                                     */
  630.  
  631. void put_queue(qt, headptr, tailptr, sizeptr)
  632. qtag    **qt;
  633. qtag    **headptr;
  634. qtag    **tailptr;
  635. int    *sizeptr;
  636. {
  637.     *sizeptr = *sizeptr + 1;
  638.  
  639.     if(!*headptr) {
  640.         *headptr = *qt;
  641.         *tailptr = *qt;
  642.         (*qt)->next = 0;
  643.         (*qt)->prev = 0;
  644.     }
  645.  
  646.     else {
  647.         (*headptr)->prev = *qt;
  648.         (*qt)->next = *headptr;
  649.         (*qt)->prev = 0;
  650.         *headptr = *qt;
  651.     }
  652. }
  653.  
  654. /**********************************************************************/
  655. /*                pull_queue                  */
  656. /**********************************************************************/
  657.  
  658. /* pull_queue removes the last queue tag on the queue specified by the */
  659. /* second and third parameters and returns that tag in the first       */
  660. /* parameter.  The fourth parameter points to a queue size counter     */
  661. /* which is decremented.                           */
  662.  
  663. void pull_queue(qt, headptr, tailptr, sizeptr)
  664. qtag     **qt;
  665. qtag    **headptr;
  666. qtag    **tailptr;
  667. int    *sizeptr;
  668. {
  669.     if(!*tailptr)
  670.         *qt = 0;
  671.     else {
  672.         *sizeptr = *sizeptr - 1;
  673.         *qt = *tailptr;
  674.         if((*qt)->prev) {
  675.             (*qt)->prev->next = 0;
  676.             *tailptr = (*qt)->prev;
  677.         }
  678.         else {
  679.             *headptr = 0;
  680.             *tailptr = 0;
  681.         }
  682.     }
  683. }
  684.  
  685. /**********************************************************************/
  686. /*                front_queue                  */
  687. /**********************************************************************/
  688.  
  689. /* front_queue removes the queue tag pointed to by the first parameter */
  690. /* from the queue (specified by the second and third parameters) and   */
  691. /* places it back at the head of the queue.  The fourth parameter is a */
  692. /* pointer to a queue size counter, and it remains unchanged.          */
  693.  
  694. void front_queue(qt, headptr, tailptr, sizeptr)
  695. qtag    **qt;
  696. qtag    **headptr;
  697. qtag    **tailptr;
  698. int    *sizeptr;
  699. {
  700.     if((*qt)->prev) {
  701.         ((*qt)->prev)->next = (*qt)->next;
  702.         if(*qt == *tailptr)
  703.             *tailptr = (*qt)->prev;
  704.     }
  705.     if((*qt)->next) {
  706.         ((*qt)->next)->prev = (*qt)->prev;
  707.         if(*qt == *headptr)
  708.             *headptr = (*qt)->next;
  709.     }
  710.     if(!(*qt)->prev && !(*qt)->next) {
  711.         *headptr = 0;
  712.         *tailptr = 0;
  713.     }
  714.     (*qt)->next = 0;
  715.     (*qt)->prev = 0;
  716.     *sizeptr = *sizeptr - 1;
  717.  
  718.     put_queue(qt, headptr, tailptr, sizeptr);
  719. }
  720.  
  721.